<template>
  <div class="page-view-box" @contextmenu.prevent
       :class="{last:pageIndex===dataList.length-1}">
    <img @contextmenu.prevent v-if="imgSrc" :src="imgSrc" class="center" :style="divSize">
    <v-stage :config="stageConfig"
             :style="{outline: '1px solid red',...divSize}"
             class="center"
             @touchstart="handleStageMousedown"
             @mousedown="handleStageMousedown"
             ref="stage">
      <!--:class="{move:touchAction==='move'}"-->
      <!--@touchstart="handleStageMousedown"-->
      <!--@mousedown="handleStageMousedown"-->
      <!--@contextmenu="handleStageContextmenu"-->
      <v-layer>
        <v-text :config="{text:'加载中'}" v-if="!img"/>
        <v-group v-else :config="imageGroupConfig">
          <!--绘制标记、选区-->
          <v-group :config="getMarkGroupConfig(item)" v-for="(item,index) in markShowList"
                   :key="'mark'+index">
            <v-rect v-if="isSelectionLeftControlShow(item)"
                    @touchstart="handleControlMove($event,item)"
                    :config="getSelectionLeftControlConfig(item)"/>
            <!--@mousedown="handleControlMove($event,item)"-->
            <v-rect :config="getMarkConfig(item)"
                    @mouseenter="handleMarkMouseenter(item.mark,$event)"
                    @click="handleMarkClick(item.mark,$event)"
                    @mouseout="handleMarkMouseout(item.mark,$event)"
            />
            <v-Line :config="getMarkUnderLineConfig(item)"/>
            <v-rect v-if="isSelectionRightControlShow(item)"
                    @touchstart="handleControlMove($event,item,false)"
                    :config="getSelectionRightControlConfig(item)"/>
            <!--@mousedown="handleControlMove($event,item,false)"-->
          </v-group>
        </v-group>
        <v-text :config="textConfig"/>
      </v-layer>
    </v-stage>
    <!--<div style="position:absolute;top: 0;left: 0" @click="test">toggleHitCanvas</div>-->
  </div>
</template>

<script>
  // import Hammer from 'hammerjs'
  import VueKonva from "../../vue-konva"
  import Hammer from '../../../util/hammer-konva'

  // const Hammer = require('../../../util/hammer-konva')
  // console.log(Hammer)

  import pageMixin from "./pageMixin";
  import {addEventListener, removeEventListener} from "@/util/eventManager";

  const {vStage, vLayer, vGroup, vText, vImage, vLine, vRect} = VueKonva
  export default {
    name: "PageView",
    components: {vStage, vLayer, vGroup, vText, vImage, vLine, vRect},
    mixins: [pageMixin],
    props: ['data'],
    data () {
      return {
        img: null,
        markShowList: [],
        hm: null,
        touchAction: 'move',
        imgSrc: ''
      }
    },
    computed: {
      boxSize () {
        return {
          height: this.stageSize.height + "px",
          width: this.stageSize.width + "px"
        }
      },
      divSize () {
        let height = this.stageSize.height
        let width = this.stageSize.width
        if (this.img) {
          height = this.img.height * this.scale * this.imgScale
          width = this.img.width * this.scale * this.imgScale
        } else {
          height = this.maxHeight * this.scale * this.imgScale
          width = this.maxWidth * this.scale * this.imgScale
        }
        return {
          width: width + 'px',
          height: height + 'px'
        }
      },
      imageGroupConfig () {
        if (!this.img) return
        return {
          height: this.img.height,
          width: this.img.width,
          scale: {
            x: this.imgScale,
            y: this.imgScale,
          }
        }
      },
      imgSize () {
        if (!this.img) return
        return {
          height: this.img.height,
          width: this.img.width
        }
      },
      imgScale () {
        if (!this.imgSize) return 1
        return Math.min(this.maxWidth / this.imgSize.width, this.maxHeight / this.imgSize.height)
      },
      pageIndex () {
        return this.data.pageIndex
      },
      stageConfig () {
        let height = this.stageSize.height
        let width = this.stageSize.width
        if (this.img) {
          height = this.img.height * this.scale * this.imgScale
          width = this.img.width * this.scale * this.imgScale
          // height = this.maxHeight * this.scale
          // width = this.maxWidth * this.scale
        }
        return {
          // listening: false,
          width,
          height,
          scale: {
            x: this.scale,
            y: this.scale,
          }
        }
      },
      textConfig () {
        return {
          text: `${this.pageIndex}`,
          fontSize: 30,
          scale: {
            x: this.imgScale,
            y: this.imgScale,
          }
        }
      },
      // imageConfig() {
      //   if (!this.img) return
      //   return {
      //     image: this.img
      //   }
      // },
      // markShowList() {
      //   console.log(this.markList)
      // }
    },
    watch: {
      markList () {
        this.addTask(this.loadMarkList)
      },
    },
    async mounted () {
      await this.initPage()

      let stage = this.getStage()

      let hammertime = new Hammer(stage, {domEvents: true});
      // hammertime.add(new Hammer.Press())
      stage.on('press', (ev) => {
        let A = this.getWordByPointerPosition(ev.evt.gesture)
        let start = `${A.pageIndex}-${A.index}`

        this.addMark({
          markid: 'selection-mark',
          start: start,
          end: start,
          config: {
            stroke: '',
            strokeWidth: 0,
            fill: this.selectionBgColor,
            name: 'selection'
          },
          touch: true,
          A: {...A, position: 'left'},
          B: {...A, position: 'right'},
        })
        setTimeout(() => {
          let selection = this.getSelection()
          if (selection) this.sendEvent('selection-change', selection, ev.evt.gesture)
        }, 50)
        // e.preventDefault()
        // if (e.pointerType === 'touch') {
        //   this.handleSelectText(e)
        // }
      });
      // stage.on('panstart', this.handleStageMousedown);
    },
    beforeDestroy () {
      console.log('页面', this.pageIndex, '销毁')
      if (this.hm) this.hm.destroy()
      // removeEventListener('mousemove', this.onMousemove, this.$refs.page.$el)
      // removeEventListener('mousedown', this.onMousedown, this.$refs.page.$el)
      // removeEventListener('mouseup', this.onMouseup, this.$refs.page.$el)
    },
    methods: {
      test () {
        let stage = this.getStage()
        stage.getLayers()[0].toggleHitCanvas()
      },
      getImg (src) {
        return new Promise((resolve, reject) => {
          let img = new Image()
          img.onload = e => resolve(img)
          img.src = src
        })
      },
      getMarkConfig (config) {
        let c = JSON.parse(JSON.stringify(config))
        if (c.strokeWidth) c.strokeWidth = c.strokeWidth / this.imageGroupConfig.scale.x / this.scale
        if (c.type === 'underline') {
          c.stroke = 'transparent'
          c.fill = 'transparent'
        }
        return {
          ...c,
          x: 0,
          y: 0
        }
      },
      getMarkGroupConfig (config) {
        let c = JSON.parse(JSON.stringify(config))
        // if (c.strokeWidth) c.strokeWidth = c.strokeWidth / this.imageGroupConfig.scale.x / this.scale
        return {
          x: c.x,
          y: c.y,
          width: c.width,
          height: c.height,
          // listening: true
        }
      },
      getMarkUnderLineConfig (config) {
        let c = JSON.parse(JSON.stringify(config))

        let points = [0, c.height, c.width, c.height]

        // if (item.config.type === 'underline') {
        //   // console.log(_item.height)
        //   _item.y = _item.y + _item.height
        //   _item.height = 0
        // }
        return {
          points,
          strokeWidth: c.strokeWidth,
          stroke: c.stroke,
        }
      },
      getPointerPositionOnImage () {
        let pos = this.getPointerPositionOnStage()
        return {
          x: pos.x / this.scale,
          y: pos.y / this.scale,
        }
      },

      getPointerPositionOnStage () {
        console.log(this.pageIndex)
        let ev = event
        let pos = this.getStage().getPointerPosition()

        // if (ev.targetTouches) ev = ev.targetTouches[0]

        let {x, y} = pos

        // console.log(this.pageIndex, pos);

        // if (pos) {
        //   this.dx = ev.screenX - pos.x
        //   this.dy = ev.screenY - pos.y
        // }

        // let x = ev.screenX - this.dx
        // let y = ev.screenY - this.dy

        if (x < 0) x = 0
        else if (x > this.stageConfig.width) x = this.stageConfig.width

        if (y < 0) y = 0
        else if (y > this.stageConfig.height) y = this.stageConfig.height

        return {x, y}
      },
      getSelectionLeftControlConfig (config) {
        let c = JSON.parse(JSON.stringify(config))
        return {
          hitStrokeWidth: 20,
          x: -10,
          y: 0,
          width: 10,
          height: c.height,
          fill: 'red',
          // listening: true
        }
      },
      getSelectionRightControlConfig (config) {
        let c = JSON.parse(JSON.stringify(config))
        return {
          hitStrokeWidth: 20,
          x: c.width,
          y: 0,
          width: 10,
          height: c.height,
          fill: 'red'
        }
      },
      getStage () {
        return this.$refs.stage.getStage()
      },
      isSelectionLeftControlShow (item) {
        return item.mark.markid === 'selection-mark' && item.mark.touch && item.currIdx === 0
      },
      isSelectionRightControlShow (item) {
        return item.mark.markid === 'selection-mark' && item.mark.touch && item.currIdx === item.total - 1
      },
      handleControlMove (evt, item, isLeft = true) {
        evt.cancelBubble = true;
        let move = e => {
          let C = this.getWordByPointerPosition()
          let newA = isLeft ? C : item.mark.A
          let newB = isLeft ? item.mark.B : C

          if (newA.pageIndex > newB.pageIndex || (newA.pageIndex === newB.pageIndex && newA.index > newB.index)) {
            [newA, newB] = [newB, newA]
          }

          let pos = this.getPos(newA, newB)

          if (!pos) return

          this.addMark({
            markid: 'selection-mark',
            start: pos.start,
            end: pos.end,
            config: {
              stroke: '',
              strokeWidth: 0,
              fill: this.selectionBgColor,
              name: 'selection'
            },
            touch: true,
            A: newA,
            B: newB,
          })
        }
        let up = e => {
          this.$nextTick(() => {
            let selection = this.getSelection()
            if (selection) this.sendEvent('selection-change', selection)
          })
        }
        this.openMask(move, up)
      },
      handleMarkClick () {
      },
      handleMarkMouseenter () {
      },
      handleMarkMouseout () {
      },
      async initPage () {
        // this.hm = new Hammer.Manager(this.$refs.page.$el)
        // this.hm.add(new Hammer.Pan())
        // this.hm.add(new Hammer.Tap())
        // this.hm.on('tap', this.onTap)
        // this.hm.on('panstart', this.onPanstart)
        // this.hm.on('panmove', this.onPanmove)

        // addEventListener('mousedown', this.onMousedown, this.$refs.page.$el)
        // addEventListener('mousemove', this.onMousemove, this.$refs.page.$el)
        // addEventListener('mouseup', this.onMouseup, this.$refs.page.$el)

        console.log('页面', this.pageIndex, '开始加载图片')
        let imgSrc = await this.getImgSrc(this.data.img)
        // console.log(imgSrc)
        await this.loadImg(imgSrc)
        console.log('页面', this.pageIndex, '图片加载完成')

        console.log('页面', this.pageIndex, '开始加载文字')
        await this.loadText()
        console.log('页面', this.pageIndex, '文字加载完成')

        this.addTask(this.loadMarkList)
      },
      async loadImg (src) {
        this.img = await this.getImg(src)
        this.imgSrc = src
        // if (this.img.width > this.maxWidth) this.maxWidth = this.img.width
        // if (this.img.height > this.maxHeight) this.maxHeight = this.img.height
      },
      async loadText () {
        await this.getText(this.pageIndex)
      },

      async loadMarkList () {
        let arr = []
        for (let i = 0; i < this.markList.length; i++) {
          let item = this.markList[i]
          let pageIndex = Number(item.start)
          if (isNaN(pageIndex)) {
            let startIndex = ''
            let endIndex = ''
            if (/^(\d+)-(\d+)$/.test(item.start)) startIndex = Number(RegExp.$1)
            if (/^(\d+)-(\d+)$/.test(item.end)) endIndex = Number(RegExp.$1)
            if (this.pageIndex >= startIndex && this.pageIndex <= endIndex) {
              pageIndex = this.pageIndex
            }
          }
          if ((typeof pageIndex !== 'number') || (pageIndex !== this.pageIndex)) {
            continue
          }
          let show = this.alwaysShowMarkTypes.indexOf(item.type) > -1
          if (!this.markShow && item.config.name !== 'selection' && !show) continue
          // item.config.name==='selection'
          let A = await this.getWordByIndexPos(item.start)
          let B = await this.getWordByIndexPos(item.end)
          let tRows = await this.getWrodsAToB(A, B)
          if (tRows) {
            let text = ''
            let rows = Object.keys(tRows)
            let total = rows.length
            rows.map((name, idx) => {
              let $item = tRows[name]
              text += `${$item.text}\n`
              if ($item.page === this.pageIndex) {
                let _item = {
                  ...item.config,
                  x: $item.x,
                  y: $item.y,
                  width: $item.width,
                  height: $item.height,
                  mark: item,
                  currIdx: idx,
                  total
                }
                if (_item.strokeWidth) {
                  _item.strokeWidth = _item.strokeWidth / this.imageGroupConfig.scale.x / this.scale
                }
                if ($item.height < 0) {
                  _item.y = _item.y + $item.height
                  _item.height = Math.abs(_item.height)
                }
                if (!_item.fill && !_item.stroke) {
                  _item.fill = 'rgba(255,0,0,0.3)'
                }
                // if (item.config.type === 'underline') {
                //   // console.log(_item.height)
                //   _item.y = _item.y + _item.height
                //   _item.height = 0
                // }
                arr.push(_item)
              }
            })
            // for (let name in tRows) {
            //   let $item = tRows[name]
            //   text += `${$item.text}\n`
            //   if ($item.page === this.pageIndex) {
            //     let _item = {
            //       ...item.config,
            //       x: $item.x,
            //       y: $item.y,
            //       width: $item.width,
            //       height: $item.height,
            //       mark: item,
            //       currIdx: curr
            //     }
            //     if (_item.strokeWidth) {
            //       _item.strokeWidth = _item.strokeWidth / this.imageGroupConfig.scale.x / this.scale
            //     }
            //     if ($item.height < 0) {
            //       _item.y = _item.y + $item.height
            //       _item.height = Math.abs(_item.height)
            //     }
            //     if (!_item.fill && !_item.stroke) {
            //       _item.fill = 'rgba(255,0,0,0.3)'
            //     }
            //     // if (item.config.type === 'underline') {
            //     //   // console.log(_item.height)
            //     //   _item.y = _item.y + _item.height
            //     //   _item.height = 0
            //     // }
            //     arr.push(_item)
            //   }
            // }
            item.text = text.substr(0, text.length - 1)
          } else {
            try {
              let _item = {
                ...item.config,
                ...JSON.parse(item.end),
                mark: item
              }
              if (!_item.fill && !_item.stroke) {
                _item.stroke = 'rgba(255,0,0,1)'
              }
              arr.push(_item)
            } catch (e) {
              console.error('被吃掉的错误', e)
            }
          }
        }
        this.markShowList = arr
      },
      // onPanstart(e) {
      //   let word = this.getWordByPointerPosition()
      //   this.eventBus.emit('select-text-start', word)
      //   let panend = e => {
      //     this.eventBus.emit('select-text-end')
      //     this.hm.off('panend', panend)
      //   }
      //   this.hm.on('panend', panend)
      // },
      onMousedown (e) {
        this.clearSelection()
        if (this.pointerType === 'text') {
          let word = this.getWordByPointerPosition()
          this.eventBus.emit('select-text-start', word)
        }
        let mouseup = e => {
          this.onMouseup(e)
          removeEventListener('mouseup', mouseup)
        }
        addEventListener('mouseup', mouseup)
      },
      onMousemove (e) {
        if (this.moveTask === 'selectText') {
          let word = this.getWordByPointerPosition()
          console.log(word.text)
          if (word) this.eventBus.emit('select-text-move', word)
        }
      },
      onMouseup () {
        if (this.moveTask === 'selectText') {
          this.eventBus.emit('select-text-end')
        }
      },
      onTap (e) {
        // console.log(this.getPointerPositionOnImage());
        // console.log(this.getWordByPointerPosition());
        this.clearSelection()
      },
    }
  }
</script>

<style scoped lang="scss">
  .page-view-box {
    height: 100%;
    width: 100%;
    /*margin-bottom: 5px;*/
    position: relative;
    /*background-color: #409EFF;*/
    outline: 1px solid #409EFF;

    .center {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      margin: auto;
    }

    &.last {
      margin-bottom: 0;
    }

    &.move {
      touch-action: auto !important;
    }

    .text-box {
      user-select: text;

      .text-item {
        position: absolute;
        color: transparent;

        &::selection {
          background-color: rgba(64, 158, 255, 0.5);
          /*color: rgba(255, 255, 255, 0.5);*/
        }
      }
    }
  }
</style>
